package org.fone.utils.task;

import org.fone.pojo.Table;
import org.fone.pojo.TableField;
import org.fone.service.TableService;
import org.fone.utils.task.data.TaskType;
import org.omg.IOP.TAG_ALTERNATE_IIOP_ADDRESS;
import org.springframework.util.ObjectUtils;

import javax.print.DocFlavor;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

import static cn.hutool.core.lang.Console.log;

/**
 * 数据流运行
 */
public class TaskRunner {
    private Map<Integer,Task> tasks;
    private Map<Integer,List<Integer>> links;
    private Map<Integer, Table> resultMap = new HashMap<>();
    private Map<Integer,Boolean> check_map = new HashMap<>();
    List<Task> selectors = new ArrayList<>();

    TableService tableService;
    public TaskRunner(Map<Integer,Task> tasks,Map<Integer,List<Integer>> links,TableService tableService) {
        this.tasks = tasks;
        this.tableService=tableService;
        this.links=links;
        tasks.forEach((task_id,task)->{
            if (task.type== TaskType.SELECTOR) selectors.add(task);
        });
    }

    public Map<Integer,Table> getResultData() {
        return resultMap;
    }
    public int check(){
        if (ObjectUtils.isEmpty(tasks)) return 0;
        int flag = 0;
        //从selector开始
        for (Task selector : selectors){
            flag = checkTask(selector);
            if (flag!=0) return flag;
        }
        return flag;
    }
    int checkTask(Task task) {
        int flag=0;
        if (task.type==TaskType.MERGER){
            for (int source_id:((Merger)task).source_ids){
                if (!check_map.containsKey(source_id)){
//                    log("数据源还没准备完成，此次递归结束！");
                    return 0;
                }
            }
        }else if (task.type==TaskType.END) return 0;//结束
        else {
            if (check_map.containsKey(task.task_id)) return task.task_id;//有闭环
            check_map.put(task.task_id,true);
        }
        if (!links.containsKey(task.task_id)) return task.task_id;//连接信息有误
        for (int next_id:links.get(task.task_id)){
            //task 的直属子节点
            if (!tasks.containsKey(next_id)) return next_id;
            flag=checkTask(tasks.get(next_id));
            if (flag!=0) return flag;
        }
        return flag;
    }

    /**
     * 开始运行，按顺序运行，入口
     * @return 成功则返回0，失败则返回失败的 id（最后一个task必为终结task，即结束）
     */

    public int run(){
        if (ObjectUtils.isEmpty(tasks)) return 0;
//        List<Task> selectors = new ArrayList<>();
//        tasks.forEach((task_id,task)->{
//            if (task.type== TaskType.SELECTOR) selectors.add(task);
//        });
        int flag = 0;
        //从selector开始
        for (Task selector : selectors){
            flag = runTask(selector);
            if (flag>0) return flag;//-1,0都正常
        }

        return flag;
    }

    //成功则返回0，失败则返回失败者id
    private int runTask(Task task) {
        log("#################################");
        log(task.getClass().getName(),"开始执行，id="+task.task_id);
        log("---------------------------------");
        int flag=0;
        try {
            switch (task.type){
                case FILTER: flag=runFilter((Filter) task);break;
                case MERGER: flag=runMerger((Merger) task);break;
                case SENIOR: flag=runSenior((Senior) task);break;
                case SELECTOR: flag=runSelector((Selector) task);break;
                case END: runEnd((End)task);return flag;
                default:return flag;
            }
            if (flag!=0) return flag;
//        if (!links.containsKey(task.task_id)) return task.task_id;
            for (int next_id:links.get(task.task_id)){
                //task 的直属子节点
                flag=runTask(tasks.get(next_id));
                if (flag!=0) return flag;
            }
        }catch (Exception e){
            e.printStackTrace();
            return task.task_id;
        }
        return flag;
    }

    private void runEnd(End end) {
        resultMap.put(end.task_id,resultMap.get(end.source_id));
    }


    /**
     * 运行选择器，选择一个表格
     * @param selector 选择器
     * @return 成功则返回 0
     */
    private int runSelector(Selector selector) {
        log("加载表格：",selector.source_name);
        Table table = tableService.readTable(selector.source_name);
        if (table==null) return selector.task_id;
        resultMap.put(selector.task_id,table);
        log("结果：",table);
        return 0;
    }
    private int runFilter(Filter filter) {
        log("加载：",filter.source_id);
        if (!resultMap.containsKey(filter.source_id)) return filter.task_id;
        Table table = resultMap.get(filter.source_id).clone();
        log("筛选前：",table);

        switch (filter.field_type){
            case NUMBER:TableEditor.numberFilter(table, filter.field, filter.operator, Long.parseLong(filter.value)); break;
            case STR:TableEditor.strFilter(table, filter.field, filter.operator,filter.value); break;
            case DATE:TableEditor.dateFilter(table, filter.field, filter.operator,filter.value); break;
        }
        log("筛选后：",table);
        resultMap.put(filter.task_id,table);
        return (table==null)? filter.task_id:0;
    }
    private int runMerger(Merger merger) {
        log("合并：");
        if (merger.source_ids.size()!=2)return 0;
        for (int source_id:merger.source_ids){
            if (!resultMap.containsKey(source_id)){
                log("数据源还没准备完成，此次递归结束！");
                return -1;
            }
        }
        log("合并源：",merger.source_ids);
        log("tab1：",resultMap.get(merger.source_ids.get(0)));
        log("tab2：",resultMap.get(merger.source_ids.get(1)));
        Table table = TableEditor.merger(resultMap.get(merger.source_ids.get(0)),resultMap.get(merger.source_ids.get(1)),merger.union,merger.getMatch_relationship(),merger.getOut_fields(),merger.source_ids);
        resultMap.put(merger.task_id,table);
        log("合并结果：",table);
        return 0;
    }

    private int runSenior(Senior senior) {
        System.out.println("高级筛选！");
        System.out.println(senior);
        log("加载：",senior.source_id);
        if (!resultMap.containsKey(senior.source_id)) return senior.task_id;
        Table table = (Table) resultMap.get(senior.source_id).clone();
        log("筛选前：",table);

        switch (senior.operator){
            case ADD_LEFT:;
            case ADD_RIGHT:;
            case ADD:TableEditor.addColumnValue(table,senior.operator,senior.field_type,senior.field,senior.value);break;
            case SUB:TableEditor.subColumnValue(table,senior.field_type,senior.field,senior.value);break;
            case INSERT:TableEditor.insertColumn(table,senior.field_type,senior.field,senior.value);break;
        }
        log("筛选后：",table);
        resultMap.put(senior.task_id,table);
        return (table==null)? senior.task_id:0;
    }
}
